from nicegui import ui, app, events
import json
import os
import orm
from tools.search import Search
from tools.loginout import logout
from orm import manager
from pages.page_structure import init_page


class question_card():
    def callback(self, option):
        self.onclick()
        selected = self.selected[option]
        ori = self.saver[str(self.questionid)]
        if (selected == True):
            ori = ori + option
        else:
            ori = ori.replace(option, "")
        self.saver[str(self.questionid)] = ori

    def onclick(self):
        self.missing.set_visibility(False)

    def check_result(self, correct):
        mine = self.saver[self.questionid]
        if ((self.type == "input") or (self.type == 'single')):
            if mine == correct:
                self.correct.set_visibility(True)
                return True
        elif (self.type == 'multiple'):
            if len(mine) == len(correct):
                flag = True
                for c in list(correct):
                    flag = flag and (c in mine)
                if (flag):
                    self.correct.set_visibility(True)
                    return True
        with self.card:
            with ui.card().classes("bg-orange-500 px-[10px]"):
                ui.label("错误， 正确答案{}".format(correct))
        return False

    def create_card(self):
        with ui.card().classes("w-full") as self.card:
            self.missing = ui.badge('未做', color='red').props('floating').classes("animate-ping")
            self.correct = ui.badge('正确！', color='green').props('floating').classes("animate-ping")
            self.missing.set_visibility(False)
            self.correct.set_visibility(False)
            quesjson = json.loads(self.question.content)
            with ui.column().classes('w-full'):
                ui.label(quesjson["name"])
                ui.markdown(quesjson["content"]).classes("w-full")
                self.type = quesjson["type"]
                if quesjson["type"] == 'input':
                    ui.input("输入答案", on_change=lambda: self.onclick()).bind_value_to(self.saver, str(self.question.id))
                elif quesjson["type"] == 'single':
                    ui.radio(quesjson["options"], on_change=lambda: self.onclick()).classes(
                        "w-full colot=blue").bind_value_to(self.saver, str(self.question.id))
                elif quesjson["type"] == "multiple":
                    self.saver[str(self.question.id)] = ""
                    self.selected = {}
                    for key in quesjson["options"]:
                        self.selected[key] = False
                    for key in quesjson["options"]:
                        ui.checkbox(quesjson["options"][key], on_change=lambda option=key: self.callback(option)) \
                            .bind_value_to(self.selected, key)
    def __init__(self, question, saver=None, pop = False):
        self.questionid = str(question.id)
        self.question = question
        if (saver == None):
            self.saver = {}
        else:
            self.saver = saver
        if not pop:
            self.create_card()
        else:
            with ui.dialog() as self.dialog:
                self.create_card()
            self.dialog.open()


    def show_missing(self):
        self.missing.set_visibility(True)


@ui.page("/question_group/{gid}/do")
async def do_question_group(gid: str):
    question_group = manager.get_questiongroup_by_groupid(int(gid))[0]
    if not manager.questiongroup_is_visible_for(question_group, app.storage.user["username"]):
        ui.button("无权限，返回主页", on_click=lambda: ui.open('/'))
    else:
        init_page(False)
        questions = manager.get_question_by_group(question_group)
        result = {}
        cards = []
        questionid_to_content = {}
        for question in questions:
            cards.append(question_card(question, result))
            questionid_to_content[str(question.id)] = question.content

        def submit():
            missing = []
            for id in result:
                if result[id] == None or result[id] == '':
                    missing.append(id)
            if len(missing) > 0:
                for card in cards:
                    if card.questionid in missing:
                        card.show_missing()
            else:
                correctcount = 0
                allcount = len(questions)
                for card in cards:
                    quesjson = json.loads(questionid_to_content[card.questionid])
                    score = 0
                    if card.check_result(quesjson["answer"]):
                        correctcount += 1
                        score = 100
                    manager.add_solution_history(username=app.storage.user['username'],
                                                 question_id=int(card.questionid), score=score,
                                                 answer=result[card.questionid])
                submitButton.set_visibility(False)
                with ui.dialog() as dialog_finish, ui.card().classes("w-[800px]  h-[800px] bg-gradient-to-br from-blue-400 to-purple-300"):
                    with ui.column().classes("w-full h-fit my-auto"):
                        ui.label("恭喜你，完成本次做题").classes("mx-auto w-full text-center text-yellow-400 text-5xl mt-3")
                        ui.label("共{}道，正确{}道".format(allcount, correctcount)).classes('mx-auto w-full text-center text-cyan-300 text-3xl m-9')
                        ui.circular_progress(min = 0, max = 100, size ="300px",show_value=False, value=correctcount/allcount*100).classes(
                            "mx-auto w-full mb-9",
                        )

                dialog_finish.open()

        submitButton = ui.button("提交", on_click=lambda: submit()).classes("w-full")
        ui.button("退出", on_click=lambda: ui.open("/question_group/{}".format(gid)))


@ui.page("/question_group/{gid}")
async def question_group_page(gid: str):
    question_group = manager.get_questiongroup_by_groupid(int(gid))[0]
    if not manager.questiongroup_is_visible_for(question_group, app.storage.user["username"]):
        ui.button("无权限，返回主页", on_click=lambda: ui.open('/'))
    else:
        init_page()

        def delete_question_group():
            succ, res = manager.delete_questiongroup(question_group, app.storage.user["username"])
            ui.notify(res)
            if succ:
                ui.open("/question_groups")

        def delete_question(q):
            succ, res = manager.delete_question(q, app.storage.user["username"])
            ui.notify(res)

        def manage_visible():
            visible_user_group = list(manager.select_usergroup_allowed_by_questiongroup(question_group))
            if (question_group.is_public):
                ui.notify("已经是公开问题组")
                return

            def update_show():
                with visible_result:
                    visible_result.clear()
                    for vg in visible_user_group:
                        with ui.row().classes("w-full justify-end"):
                            ui.label(vg.group_name).classes("mx-auto grow")
                            ui.button("移除可见", on_click=lambda g=vg : delete_group_from_visible(g), color='text-indigo-700')\
                                .classes("mx-auto grow-0 bg-gradient-to-br from-purple-200 to-blue-200")

            def delete_group_from_visible(g):
                visible_user_group.remove(g)
                manager.delete_usergroup_to_questiongroup(g, question_group)
                update_show()

            def add_visible_group():
                def add_group_to_visible(g):
                    visible_user_group.append(g)
                    update_show()
                    manager.add_usergroup_to_questiongroup(g, question_group)
                    dialog_search.close()

                def search_input(value):
                    groups = manager.search_usergroup_bu_groupname(value)
                    with search_result:
                        search_result.clear()
                        for group in groups:
                            if group in visible_user_group:
                                continue
                            with ui.row().classes("w-full px=[20px]"):
                                ui.label(group.group_name).classes("grow")
                                ui.button("添加", on_click=lambda g=group: add_group_to_visible(g))

                with ui.dialog() as dialog_search, ui.card().tight().classes('w-[400px] h-[400px]'):
                    ui.input("搜索用户组名", on_change=lambda e: search_input(e.value)).classes("w-full")
                    search_result = ui.card().classes("w-full h-full")
                dialog_search.open()
                search_input("")

            with ui.dialog() as dialog, ui.card().tight().classes('w-[800px] h-fit'):
                with ui.column().classes("w-full px-[50px] py-[20px]").bind_visibility_from(app.storage.user,
                                                                                            "isnotpublic"):
                    ui.button("添加可见用户组", on_click=lambda: add_visible_group(), color='text-indigo-700')\
                        .classes("mx-auto bg-gradient-to-br from-purple-200 to-blue-200")
                    visible_result = ui.card().classes("w-full")
            update_show()
            dialog.open()

        def add_question():
            with ui.dialog() as dialog_addquestion, ui.card().tight().classes('w-[400px] h-[400px]'):
                def handle_upload(e: events.UploadEventArguments):
                    text = e.content.read().decode('utf-8')
                    questions = json.loads(text)
                    for question in questions:
                        if (not ("name" in question)) or (not ("content" in question)) or (not ("type" in question)):
                            ui.notify("问题格式错误，缺少name/content/type")
                            continue
                        if not (question["type"] in ["single", 'multiple', 'input']):
                            ui.notify("问题类型错误，必须是single/multiple/input")
                            continue
                        manager.add_question(question_group, question, app.storage.user["username"])
                    ui.notify("问题添加完成")

                ui.upload(on_upload=handle_upload).props('accept=.json').classes('w-full')
            dialog_addquestion.open()

        def upload_image():
            with ui.dialog() as dialog_image, ui.card().tight().classes('w-[400px] h-[400px]'):
                def handle_upload(e: events.UploadEventArguments):
                    filename = e.name
                    global_file_id = app.storage.general.get("global_file_id", 0)
                    app.storage.general["global_file_id"] = global_file_id + 1
                    if not os.path.exists("./images"):
                        os.mkdir("./images")
                    with open('./images/{}{}'.format(global_file_id, filename), 'wb') as f:
                        f.write(e.content.read())
                    ui.notify("图片上传完成")
                    urlshow.set_text('/images/{}{}'.format(global_file_id, filename))

                ui.upload(on_upload=handle_upload).props().classes('w-full')
                urlshow = ui.label()
            dialog_image.open()

        def preview(q):
            with ui.dialog() as dialog_preview, ui.card().tight().classes('w-[1500px] h-fit'):
                question_card(q)
            dialog_preview.open()

        with ui.row().classes("w-full"):
            ui.label(question_group.group_name)
            ui.button("Exercise！", color='text-indigo-10',
                      on_click=lambda: ui.open("/question_group/{}/do".format(gid))) \
                .classes("bg-green-400 grow")
            ui.button("更新可见性", on_click=lambda: manage_visible())
            ui.button("上传图片", icon="image", on_click=lambda: upload_image())
            ui.button("添加问题", on_click=lambda: add_question())
            ui.button("删除问题组", on_click=lambda: delete_question_group(), color='text-indigo-10') \
                .classes("bg-red-600 text-white")
        questions = manager.get_question_by_group(question_group)
        for question in questions:
            with ui.card().classes("w-full bg-gradient-to-br from-purple-50 to-blue-50"):
                with ui.row().classes("grow w-full"):
                    with ui.expansion(question.question_name).classes():
                        ui.label(question.content.encode('utf-8').decode('unicode_escape'))
                    with ui.row().classes("grow justify-end"):
                        ui.button("查看", on_click=lambda q=question: preview(q), color='text-indigo-700')\
                            .classes("grow-0 bg-gradient-to-br from-purple-200 to-blue-200")
                        ui.button("删除", on_click=lambda q=question: delete_question(q), color='text-indigo-700')\
                            .classes('grow-0 bg-gradient-to-br from-purple-200 to-blue-200')


@ui.page("/question_groups")
async def question_groups_page():
    def add_question_group():
        visible_user_group = []

        def add_visible_group():
            def add_group_to_visible(g):
                visible_user_group.append(g)
                with visible_result:
                    visible_result.clear()
                    for vg in visible_user_group:
                        ui.label(vg.group_name).classes("w-full mx-auto")
                dialog_search.close()

            def search_input(value):
                groups = manager.search_usergroup_bu_groupname(value)
                with search_result:
                    search_result.clear()
                    for group in groups:
                        if group in visible_user_group:
                            continue
                        with ui.row().classes("w-full px=[20px]"):
                            ui.label(group.group_name).classes("grow")
                            ui.button("添加", on_click=lambda g=group: add_group_to_visible(g),
                                      color='text-indigo-700')\
                                .classes("my-auto bg-gradient-to-br from-purple-200 to-blue-200")

            with ui.dialog() as dialog_search, ui.card().tight().classes('w-[400px] h-[400px]'):
                ui.input("搜索用户组名", on_change=lambda e: search_input(e.value)).classes("w-full")
                search_result = ui.card().classes("w-full h-full")
            dialog_search.open()
            search_input("")

        def create_question_group():
            if app.storage.user.get("input_questiongroup_name", "") == "":
                ui.notify("请输入有效的用户组名")
                return
            succ, res = manager.add_questiongroup(manager.get_user(app.storage.user["username"]),
                                                  app.storage.user.get("input_questiongroup_name", ""),
                                                  not app.storage.user.get("isnotpublic", True),
                                                  visible_user_group, app.storage.user.get("input_tags"))
            ui.notify(res)
            if succ:
                dialog.close()
                ui.open("/question_groups")

        with ui.dialog() as dialog, ui.card().tight().classes('w-[800px] h-fit'):
            with ui.column().classes("w-full px-[50px] py-[50px]"):
                with ui.row().classes():
                    ui.label("问题组组名").classes("w-[200px] my-auto")
                    ui.input("输入组名").classes("my-auto text-indigo-700")\
                        .bind_value_to(app.storage.user, "input_questiongroup_name")
                with ui.row().classes():
                    ui.label("输入json列表形式的tags").classes("w-[200px] my-auto")
                    ui.input("输入tags").classes("my-auto text-indigo-700").bind_value_to(
                        app.storage.user, "input_tags"
                    )
                with ui.row().classes():
                    ui.label("是否公开").classes("w-[200px] my-auto")
                    ui.toggle({False: "公开", True: "不公开"}, value=True).bind_value_to(app.storage.user,
                                                                                         "isnotpublic").classes(
                        "my-auto")

            with ui.column().classes("w-full px-[50px] py-[20px]").bind_visibility_from(app.storage.user,
                                                                                        "isnotpublic"):
                ui.button("添加可见用户组", on_click=lambda: add_visible_group() , color='text-indigo-700')\
                    .classes("bg-gradient-to-br from-purple-200 to-blue-200 mx-auto")
                visible_result = ui.card().classes("w-full")
            ui.button("创建", on_click=lambda: create_question_group(), color='text-indigo-700')\
                .classes('w-full bg-gradient-to-br from-purple-200 to-blue-200')
        dialog.open()

    init_page()
    ui.button("添加问题组", on_click=lambda: add_question_group(), color='text-indigo-700')\
        .classes('bg-gradient-to-br from-purple-200 to-blue-200')
    if (manager.is_administrator(app.storage.user['username'])):
        ui.toggle({"True": "管理员视角", "False": "用户视角"},
                  on_change=lambda: ui.open("/question_groups"))\
            .bind_value(app.storage.user, "AdministratorView")
    # "id":x.id, "group_name":x.group_name, "creator_id":x.creator_id, "is_public":x.is_public

    visible_question_groups = list(manager.select_public_questiongroup())
    if manager.is_administrator(app.storage.user['username']) and (app.storage.user['AdministratorView'] == "True"):
        question_groups = manager.select_all_questiongroup()
    else:
        question_groups = manager.select_allowed_questiongroup_by_user(app.storage.user["username"])
    for qg in question_groups:
        if not qg in visible_question_groups:
            visible_question_groups.append(qg)
    if manager.is_administrator(app.storage.user['username']) and (app.storage.user['AdministratorView'] == "True"):
        managed_groups = manager.select_all_questiongroup()
    else:
        managed_groups = manager.select_managed_questiongroup_by_user(app.storage.user["username"])
    buttons1 = {}

    def on_click_question_group(question_group):
        ui.open("/question_group/{}".format(question_group.id))

    with ui.card().classes("h-96 w-full bg-gradient-to-br from-purple-50 to-blue-50"):
        with ui.column().classes('w-full h-full'):
            ui.label('我管理的问题组列表').classes('w-full')
            with ui.scroll_area().classes('grow'):
                for question_group in managed_groups:
                    with ui.column().classes("h-fit w-full"):
                        with ui.card().classes("h-fit w-full bg-gradient-to-br from-blue-50 to-purple-50"):
                            with ui.row().classes("my-auto w-full h-fit"):
                                with ui.card().classes("h-12 w-3/6"):
                                    with ui.row():
                                        ui.label("问题组名").classes('fond-bold')
                                        ui.label(question_group.group_name)
                                with ui.card().classes("h-12 w-1/3"):
                                    with ui.row():
                                        ui.label("创建者").classes('fond-bold')
                                        ui.label(question_group.creator_id.username)
                                ui.button("查看", icon="manage_search", color='text-indigo-700')\
                                    .classes("my-auto h-12 grow bg-gradient-to-br from-purple-200 to-blue-200") \
                                    .on("click", lambda x=question_group: on_click_question_group(x))
    with ui.card().classes("h-96 w-full bg-gradient-to-br from-purple-50 to-blue-50"):
        with ui.column().classes('w-full h-full'):
            ui.label('可见的的问题组列表').classes('w-full')
            with ui.scroll_area().classes('grow'):
                for question_group in visible_question_groups:
                    with ui.column().classes("h-fit w-full"):
                        with ui.card().classes("h-fit w-full bg-gradient-to-br from-blue-50 to-purple-50"):
                            with ui.row().classes("my-auto w-full h-fit"):
                                with ui.card().classes("h-12 w-3/6"):
                                    with ui.row():
                                        ui.label("问题组名").classes('fond-bold')
                                        ui.label(question_group.group_name)
                                with ui.card().classes("h-12 w-1/3"):
                                    with ui.row():
                                        ui.label("创建者").classes('fond-bold')
                                        ui.label(question_group.creator_id.username)
                                ui.button("查看", icon="manage_search", color='text-indigo-700',
                                          on_click=lambda x=question_group: on_click_question_group(x)).classes(
                                    "my-auto h-12 grow bg-gradient-to-br from-purple-200 to-blue-200")
